Sr. Content Developer at Microsoft, working remotely in PA, TechBash conference organizer, former Microsoft MVP, Husband, Dad and Geek.
165042 stories
·
33 followers

DuckDB has an answer to “bloated” database messages

1 Share
In this episode of The New Stack Podcast, Guillermo Sánchez Dionis, product lead at DuckLabs, explains how Quack addresses the limitations of traditional database protocols, which often introduce unnecessary overhead and inefficient data serialization.

Older database protocols were built before big data. Some still send results row by row, repeating details like column names and types with every row. The result, says DuckLabs product team lead Guillermo Sánchez Dionis, is “quite a bloated message.” That overhead adds up when you’re moving large query results.

DuckDB’s answer is Quack, an HTTP-based protocol that streams query results in batches of column data as DuckDB produces them. It was previewed in May and was released in October as part of DuckDB 2.0.0 LTS.

On this latest episode of The New Stack podcast, recorded at DuckLabs headquarters in Amsterdam, Sánchez Dionis explains how that design lets developers start working with results while a query is still running.

A database protocol is a formal set of rules and message formats that dictates how a client application communicates with a database server. It acts as a specialized language that lets a software application securely send SQL queries, receive structured data tables, and manage transactions over a network. It handles connection and authentication, query packaging, data serialization, and error management. 

But according to Sánchez Dionis, most protocols were designed pre-big data for other types of systems, with serialized rows rather than columns. They also add a lot of unnecessary data, he says, like column types and column names per row.

“It becomes quite a bloated message. That already makes the protocol not only not good for analytical systems, but it’s also quite heavy,” he contends. As protocols evolved for analytical systems, they did start using columns, but “they were still doing things like serializing one value at a time and other things that are really not efficient. Modern systems are trying to converge on using vectorized execution to be able to serialize more values at a time and trying to use more efficient representations of columnar data formats to send over the wire.”

All while the Quack protocol, he says, is aiming for a different, highly efficient approach.

Quack is DuckDB’s HTTP-based client/server protocol, with its first production release shipping in DuckDB 2.0.0 on Oct. 21. Not only does this signal Quack moving out of the preview stage, but the protocol now offers certain developer-friendly features:

  • The CONNECT statement allows developers to attach to and query a remote Quack server via standard SQL commands.
  • The new -serve CLI argument instantly starts a Quack server instance from the command line, and -connect connects to one.
  • Multiple clients can write to the same database concurrently, with transactions handled under DuckDB’s multi-version concurrency control (MVCC) isolation.

“Quack uses DuckDB’s data chunks — which is our columnar representation of data. We also serialize in a very efficient manner because we are a vectorized engine. We also make sure that we send the results in a streaming fashion,” Sánchez Dionis explains. 

“One of the most important things is tightly coupling the engine. Once you start producing results, instead of waiting for the query execution to end and then serializing all of the results at once, you serialize and send results as they are emitted by the engine. Therefore, the client can keep consuming results without having to stop the engine.”

For developers, he says, that means they don’t have to do anything. 

“I think the biggest advantage that you will see is you will have a very small memory footprint”

“You run a query from the comfort of your laptop, and you just get streaming results back. I think the biggest advantage that you will see is you will have a very small memory footprint,” he says. “What’s cool about Quack is that you install and load it wherever you are. You can also create another client on the [same] laptop with the Quack extension, and they will communicate with each other.”

Then, the scale of how many DuckDB servers is up to you and your team. And the overhead of running it on that server is next to none, Sánchez Dionis continues, as it’s Quack’s biggest efficiency gain yet.

More Quack improvements are expected in upcoming DuckDB 2.0 patch releases, as the DuckLabs team looks to build stability on the server side.

The post DuckDB has an answer to “bloated” database messages appeared first on The New Stack.

Read the whole story
alvinashcraft
53 minutes ago
reply
Pennsylvania, USA
Share this story
Delete

Recover a WebMCP Update After Its Response Disappears

1 Share

The browser showed JFK. The database already contained BOS.

That was the state of a synthetic trip after I deliberately hid the successful response to a WebMCP update. The server had committed the change, but the React editor could not prove it. Retrying the PATCH would have confused “I did not receive the response” with “the server did not apply the command.”

The safer next operation was not another write. It was a lookup of the original command.

I maintain Trip Workbench, the public React and TypeScript demo used here. The recorded trace ran with native WebMCP in HeadlessChrome 153.0.8010.0, Puppeteer 25.16.0, and a disposable PostgreSQL-compatible database. A script chose the calls; no language model selected this recovery path.

The failure is “unknown,” not “failed”

The starting draft was revision 2:

  • destination: JFK
  • purpose: Customer workshop
  • status: draft

The test called update_trip_draft with a stable command ID:

{
  "draftId": "<open-draft-id>",
  "expectedRevision": 2,
  "commandId": "audit-lost-response",
  "patch": { "destination": "BOS" }
}

After the server processed the PATCH, the harness dropped its HTTP 200 response and temporarily hid the corresponding receipt. An independent query already showed revision 3 and destination BOS. The editor still showed revision 2 and JFK.

That placement is the point of the test. Aborting before dispatch proves that no request left the browser. Dropping a response after commit produces an uncertain outcome: the client cannot honestly label the mutation either successful or failed.

Browser              Server                 Receipt store
   | PATCH cmd-123      |                        |
   |------------------->| commit revision 3      |
   |                    |----------------------->| store cmd-123
   |   response lost X  |                        |
   |                    |                        |
   | GET receipt cmd-123|                        |
   |-------------------------------------------->|
   |<---------- confirmed revision 3 ------------|

The application returned OUTCOME_UNKNOWN with the original command ID and a recheck instruction. That is not a polished error label; it is a safety boundary.

Give a mutation two identities

The update carries two identifiers with different jobs:

  • expectedRevision identifies the saved version the caller intended to change.
  • commandId identifies the logical mutation whose result may need recovery.

A revision conflict means the starting version was stale. A missing response means the caller does not know whether its command committed. Those states require different recovery paths.

Trip Workbench stores a receipt in the same server-side workflow as the mutation and exposes an authorized lookup:

GET /api/trips/:draftId/commands/:commandId

The recheck_trip_update WebMCP tool can query only the command currently attached to the editor’s unresolved outcome. It is not a general receipt browser, and it does not send another PATCH.

{
  "draftId": "<open-draft-id>",
  "commandId": "audit-lost-response"
}

Once the harness stopped hiding the receipt, the recheck confirmed that the original update moved the draft from revision 2 to 3.

This demonstrates idempotent recovery for this application contract. It is not a claim of universal exactly-once delivery across every distributed system.

Preserve the human edit made during uncertainty

While the receipt was unavailable, the test changed the visible purpose to:

Human edit while the receipt was pending

Recovery now had two truths to reconcile:

  1. The server had saved BOS and retained the previously saved purpose.
  2. The person had made a newer local edit that had never been saved.

Replacing the form with the recovered server snapshot would have destroyed the user’s work. Treating the local value as saved would have lied about persistence.

The coordinator therefore keeps the original mutation context:

type PendingOutcome = {
  draftId: string;
  commandId: string;
  kind: "update" | "submit";
  sessionGeneration: number;
  editorGeneration: number;
  ctx: AsyncOpContext;
};

AsyncOpContext retains the saved and local snapshots from dispatch time plus the edit version. The recheck reuses those snapshots. Capturing a fresh baseline only when recovery starts would erase the distinction between “present before the PATCH” and “typed after the response disappeared.”

The recovered state was intentionally split:

Observation Result
Saved destination BOS
Saved revision 3
Saved purpose Customer workshop
Visible purpose Human edit while the receipt was pending
Editor Unsaved changes
PATCH requests 1
Matching receipts 1

A later get_trip_draft returned the saved purpose and hasUnsavedChanges: true. That gives an agent enough information to avoid overwriting the person’s pending work.

Assert three surfaces, not one

The strongest part of this test is not the WebMCP response alone. The harness compares three independent surfaces:

assert.equal(toolResult.toRevision, 3);
assert.equal(visible.destination, "BOS");
assert.equal(visible.localPurpose, "Human edit while the receipt was pending");
assert.equal(visible.saveState, "Unsaved changes");
assert.equal(database.destination, "BOS");
assert.equal(database.purpose, "Customer workshop");
assert.equal(patchRequests, 1);
assert.equal(matchingReceipts, 1);

Counting receipts alone does not prove that the browser avoided a second write. Counting requests alone does not prove that the first request committed. A UI-only assertion could miss the persisted result entirely.

Harden every exit from recovery

The original trace at commit e711e20 exposed adjacent failure modes: a hung receipt request could outlive the nominal deadline, and a 401 could leave the editor marked as saving.

The later reliability pass at 0691767 adds bounded receipt lookups and releases the matching operation on authentication failure and terminal exits. It also distinguishes uncertain updates from uncertain submissions so the review screen can recheck a POST without issuing another one.

Chrome’s current WebMCP imperative API supplies an AbortSignal to tool handlers and supports cancellation of execution. That signal is necessary, but application code must still decide what cancellation means after a remote server may have committed.

The design rule I kept from this exercise is simple:

When a mutation response disappears, recover the original command before deciding whether another mutation is safe.

The useful outcome was not merely “BOS appeared.” It was one confirmed saved revision, one request, one receipt, and one human edit that remained visibly unsaved.

Read the whole story
alvinashcraft
53 minutes ago
reply
Pennsylvania, USA
Share this story
Delete

Claude Fable 5.2 vs. Opus 5.5: Same scores at almost 4x the cost

1 Share
Gold and green 3D spheres with cut-out holes linked by ribbons, evoking a Claude Fable 5.2 vs. Opus 5.5 comparison

Anthropic released Claude Fable 5.2 on November 9 and said it beats Claude Opus 5.5 in almost every capability the company measured. In the same announcement, it recommended starting with Opus for most coding and knowledge tasks, calling it its “strongest daily driver.” I wanted to find out why a company would steer people away from its best model, and whether the cheaper one really is enough.

…why a company would steer people away from its best model, and whether the cheaper one really is enough.

On Anthropic’s coding benchmarks, Fable 5.2 scored 49.1% at Xhigh effort on FrontierCode 2.0, compared with 45.5% for Opus 5.5 at Max. Anthropic also reports that Fable scored 45.3% at High effort at roughly half the cost per task of that Opus run. On FrontierSWE v2, the company reports 69.9% for Fable and 62.3% for Opus. Fable’s standard API rates are twice Opus’s: $8 per million uncached input tokens and $40 per million output tokens, versus $4 and $20.

Twice the price should make a meaningful difference, so I gave both models three coding and agent jobs and measured how well they did, how many tokens they used, what they cost, and how long they took. My tests are much smaller than Anthropic’s benchmarks and can’t prove or disprove those scores. 

The tests

I ran each model once per test through Anthropic’s API at default settings, with no turn cap. Anthropic’s API defaults on Fable and Opus aren’t equal. Fable 5.2 runs at high effort, and Opus 5.5 runs at medium, so these results show what a developer gets without tuning anything. I used a script to grade each answer the model gave for each test. The dollar figures are estimated API costs based on reported token usage. Anthropic prices uncached input, cache reads, cache writes, and output separately.

Here are the tests I ran:

  • Cron scheduler: I gave each model a written spec for code that runs when the next scheduled job runs, then sent a change request. I used a hidden suite of 50 tests to grade the final code.
  • Invoicing repo fix: Each model worked as an agent in a small invoicing library with interacting bugs in rounding, discounts, tax, and shipping. The library also had one wrong test that the model should report but not edit.
  • Incident investigation: Each model used a terminal to find the cause of a payments outage from logs, metrics, and deployment records. The data included decoy deploys and servers with wrong clocks.

The models tied with perfect scores on the first version of every test, so I made each test harder and reran it twice.

Cron scheduler

This test checks whether a model can turn a detailed spec into correct code and then absorb a change without breaking it. Here’s what differed between the versions.

  • Version 1: The spec covered standard cron schedules, such as every 15 minutes or weekdays at 9 a.m.
  • Version 2: I added rules like “the weekday nearest the 15th” and “the last Friday of the month,” and the change request reversed how two fields combine.
  • Version 3: The code had to handle time zones and daylight saving time by hand, without Python’s time zone library.

Both models scored 50/50 on all three versions. The difference was in how much work each one did to get there. Fable 5.2 wrote two to three times as much reasoning as Opus 5.5 on every version. The extra reasoning did not raise Fable’s score on any of the three versions.

The extra reasoning did not raise Fable’s score on any of the three versions.

Across the three scheduler versions, Opus matched Fable’s scores in 358 seconds versus 661 and cost an estimated $0.99 versus $3.29.

The numbers:

  • Version 1
    • Fable 5.2: 2 turns, 14,471 in, 18,732 out (11,122 reasoning), $0.87, 170 s.
    • Opus 5.5: 2 turns, 8,055 in, 9,431 out (3,846 reasoning), $0.22, 80 s.
  • Version 2
    • Fable 5.2: 2 turns, 20,215 in, 23,990 out (14,627 reasoning), $1.12, 226 s.
    • Opus 5.5: 2 turns, 14,090 in, 15,991 out (6,695 reasoning), $0.38, 131 s.
  • Version 3
    • Fable 5.2: 2 turns, 21,121 in, 28,254 out (17,452 reasoning), $1.30, 265 s.
    • Opus 5.5: 2 turns, 12,651 in, 17,205 out (6,533 reasoning), $0.39, 147 s.

Invoicing repo fix

This bug hunt is similar to the work agents do for developers daily. Here’s how I adjusted the tests with each round:

  • Version 1: The library had bugs in rounding, discounts, tax, and shipping. It also had one wrong test.
  • Version 2: I added buy-two-get-one promotions, weight-based shipping, and refunds, each with its own bugs.
  • Version 3: I added currency conversion and invoice numbering, again with bugs.

This test produced the widest gap in cost and time between the two models. Both models scored 50 of 50 on all three versions, fixing the bugs the grader covered and reporting the wrong test without editing it. Opus 5.5 used fewer reasoning tokens on every version. It finished each version in under a minute, while Fable 5.2 took about one minute and 46 seconds to just under four minutes and cost eight times as much across the three.

On these runs, Fable’s extra reasoning didn’t improve its score.

The numbers:

  • Version 1
    • Fable 5.2: 4 turns, 17,585 in, 11,511 out (5,909 reasoning), $0.58, 106 s.
    • Opus 5.5: 4 turns, 10,585 in, 2,975 out (519 reasoning), $0.09, 28 s.
  • Version 2
    • Fable 5.2: 6 turns, 88,697 in, 25,980 out (11,820 reasoning), $1.39, 223 s.
    • Opus 5.5: 4 turns, 13,938 in, 4,457 out (777 reasoning), $0.13, 39 s.
  • Version 3
    • Fable 5.2: 4 turns, 29,660 in, 24,020 out (14,022 reasoning), $1.18, 214 s.
    • Opus 5.5: 5 turns, 24,208 in, 6,013 out (1,178 reasoning), $0.17, 51 s.

Incident investigation

This test rewards careful digging more than fast coding, so I expected it to favor Fable 5.2.

Here are the changes I made for each test version.

  • Version 1: The outage data had decoy deploys and one server whose clock ran seven minutes slow.
  • Version 2: I added a clock that was corrected partway through the incident, retried requests, a compressed log file, and duplicated log lines.
  • Version 3: I added a server that logged in Chicago time and an unrelated error spike inside the incident window.

Both models scored perfectly (50 out of 50) across all three versions. Fable 5.2 took fewer turns in every version, 9 to 11 versus Opus 5.5’s 12 to 14. Across all three versions, Fable’s estimated cost was $2.54 versus Opus’s $0.91.

The numbers:

  • Version 1
    • Fable 5.2: 9 turns, 155,925 in, 14,309 out (8,638 reasoning), $0.94, 143 s.
    • Opus 5.5: 12 turns, 111,618 in, 7,405 out (2,801 reasoning), $0.25, 73 s.
  • Version 2
    • Fable 5.2: 11 turns, 168,913 in, 9,416 out (3,551 reasoning), $0.68, 105 s.
    • Opus 5.5: 13 turns, 188,846 in, 7,218 out (2,518 reasoning), $0.32, 82 s.
  • Version 3
    • Fable 5.2: 10 turns, 205,601 in, 11,887 out (4,474 reasoning), $0.92, 127 s.
    • Opus 5.5: 14 turns, 253,958 in, 7,598 out (2,041 reasoning), $0.34, 70 s.

Results

TestClaude Fable 5.2Claude Opus 5.5
Cron scheduler, 3 versions (of 150)150150
Invoicing repo fix, 3 versions (of 150)150150
Incident investigation, 3 versions (of 150)150150
Total tokens in / out722,188 / 168,099637,949 / 78,293
Total estimated cost (sum of displayed estimates)$8.98$2.29
Total time1,579 s701 s

The scores were identical across all nine runs per model. Fable 5.2 cost almost four times as much and took more than twice as long.

What do I think?

These tests give me a reason to start with Opus 5.5 for work like this. It matched Fable 5.2’s score and finished faster on every version, at about a quarter of the estimated cost overall.

That doesn’t make Fable 5.2 a bad model. My tests were hard but short. Anthropic recommends Fable for more open-ended technical work. I tested each model at its API default, so the comparison leaves open how much of the gap comes from the different effort settings.

I’d start with Opus 5.5 and move up to Fable 5.2 only when Opus stops producing ideal results.

The post Claude Fable 5.2 vs. Opus 5.5: Same scores at almost 4x the cost appeared first on The New Stack.

Read the whole story
alvinashcraft
54 minutes ago
reply
Pennsylvania, USA
Share this story
Delete

The tech products we enthusiastically recommend this holiday season

1 Share
We've been reviewing a bunch of new gadgets at TechCrunch this year, and we have some clear favorites to share for your Black Friday shopping and beyond.
Read the whole story
alvinashcraft
54 minutes ago
reply
Pennsylvania, USA
Share this story
Delete

Rust Leaves Top 10 in TIOBE Index, Making Room for Go

1 Share
"In November's edition of the TIOBE Index, Rust has dropped out of Top 10," writes I-Programmer, noting that Rust ceded the #10 position to Go. "At the same time, another Google-originated language, Dart, has entered the top 20 ousting Julia after only one month." TIOBE explains Dart's popularity is mainly being driven by Flutter, Google's framework for building cross-platform mobile applications. In fact, Flutter has become one of the major technologies for cross-platform mobile app development. The Dart language itself is not particularly unique, although it incorporates many modern programming language features. Its success is largely driven by the strength of the Flutter ecosystem and the convenience of developing applications for multiple platforms using a single codebase... [In November's ranking] Visual Basic has also lost two places, making room for R and SQL in the Top 10. Further down the ranking, Assembly has re-entered the Top 20. So TIOBE ranks the top 10 languages in November as Python, C, Java, C++, C#, JavaScript, R, SQL, Visual Basic, and Go. But I-Programmer points out that "At the top of the table, Java is back in the top 3, after over three years in 4th position," pushing C++ down to #4. Are some changes more significant than others? If you think of the ratings as shares of a pie divided into 100 pieces, there is one huge slice — Python, accounting for a over a fifth of the pie, then comes C with a slice slightly less than half of Python's. Java and C++ then have smaller slices... and C#'s share is around half of their average size. Over half the pie has now been shared between just five languages... — Next 5 (#6-10): 10.17% (JavaScript, R, SQL, Visual Basic, Go) — Next 10 (#11-20): 11.12% (Rust, PHP, Fortran, Scratch, Perl, MATLAB, Assembly, Swift, Delphi, Dart) — Next 30 (#21-50): 12.81% — Final 50 (#51-100): 12.93% [So in this month's chart...] Java has overtaken C++, but as you can see from this month's Top 10 chart they are in lock step and the difference between them is insignificant. More obvious is that Python is way ahead of all the competition and that C has an edge over Java and C++. For more discussion of this see TIOBE — Two To Rule Them All in which Mike James argued that this: confirms the standard model of programming - code is written in Python and C and everything else is just noise. Back in July we reported Rust Enters TIOBE Top 10. After four months in #10 Rust is now back at #11, which is still three places above its position, 14, a year ago. Given the way these rankings operate it only takes a very small month-on-month change for a language to lose its position and even, as has happened here it can gain in terms of its percentage ranking while still moving down. So Rust with 1.63% in November is now in #11 when it had been in #10 with 1.44%.

Read more of this story at Slashdot.

Read the whole story
alvinashcraft
54 minutes ago
reply
Pennsylvania, USA
Share this story
Delete

Meta’s Muse: How we launched the most successful consumer product this year | Mona Sarantakos

1 Share

Muse is the #1 app in the App Store and arguably the fastest-growing AI consumer product of all time. Mona Sarantakos has led product on it since day one. She’s VP of Product at Meta Superintelligence Labs and a 10-year Meta veteran with over 20 years of experience as a PM. This is her first podcast interview.

We discuss:

1. How a weekend with OpenClaw on a Raspberry Pi turned into Muse

2. Why Muse waited seven months to launch, despite getting started before most of its competitors

3. How Nat Friedman, Alex Wang, and Mark Zuckerberg each left their imprint on the product

4. How the team uses “agent swarms” to surface user insights at scale

5. The use case nobody on the team predicted

6. How Jolly, a placeholder avatar, became an icon

7. The two levers that actually move activation for an AI agent

8. The #1 thing Mona looks for in PMs today

—

Brought to you by:

WorkOS—Make your app enterprise-ready, with SSO, SCIM, RBAC, and more

DX—Engineering intelligence for the AI era

—

Episode transcript: https://www.lennysnewsletter.com/p/metas-muse-how-we-launched-the-most

—

Archive of all Lenny's Podcast transcripts: https://www.dropbox.com/scl/fo/yxi4s2w998p1gvtpu4193/AMdNPR8AOw0lMklwtnC0TrQ?rlkey=j06x0nipoti519e0xgm23zsn9&st=ahz0fj11&dl=0

—

Highlights: https://lennyspodcast.com/mostreplayedmoments

—

Where to find Mona Sarantakos:

• LinkedIn: https://www.linkedin.com/in/mona-sarantakos-a85873

• Threads: https://www.threads.com/@monachaudhuri

—

Where to find Lenny:

• Newsletter: https://www.lennysnewsletter.com

• X: https://twitter.com/lennysan

• LinkedIn: https://www.linkedin.com/in/lennyrachitsky/

—

In this episode, we cover:

(00:00) Teaser

(01:24) Introduction and Mona’s background

(02:14) A weekend with an early agentic AI

(09:08) The seven-month launch timeline

(14:07) "The claw is the law"

(15:53) Nat, Alex Wang, Zuckerberg, and how leadership shaped Muse

(23:37) The Jolly origin story

(29:53) Priority use cases and the shopping surprise

(35:03) Agentic commerce and how shopping works

(38:03) Agent swarms and synthetic data

(42:48) Evals: structure, hierarchy, and who writes them

(46:37) Activation and word of mouth

(51:09) The design bets that defined Muse

(57:04) Prototyping culture and the two Muses that fought

(01:01:54) How the PM role has changed

(01:09:05) Muse's first prototype

(01:10:37) The board meeting prototype that almost didn’t work

(01:12:00) Team size, closeness, and culture

(01:20:55) What comes next: ambient agents and financial betterment

—

Referenced:

• Muse: https://muse.ai

• Introducing Muse Spark: MSL’s First Model, Purpose-Built to Prioritize People: https://about.fb.com/news/2026/04/introducing-muse-spark-meta-superintelligence-labs

• Nat Friedman’s website: https://nat.org

• OpenClaw: https://openclaw.ai

• From skeptic to true believer: How OpenClaw changed my life | Claire Vo: https://www.lennysnewsletter.com/p/how-openclaw-changed-my-life-claire-vo

• Personal Superintelligence: https://www.meta.com/superintelligence

• The Future is for Everyone: https://www.meta.com/thefutureisforeveryone

• Grok Bot: https://x.ai/bot

• How we built Grok Bot in a month | Roman Ugarte (SpaceXAI): https://www.lennysnewsletter.com/p/how-we-built-grok-bot-in-a-month

• Claude Duet: https://claude.com/product/claude-duet

• Dots: https://openai.com/index/introducing-dots

• Alex Wang on X: https://x.com/alexandr_wang

• Alex Cornell’s website: https://www.alexcornell.com

• How I AI: How Meta designed Muse with Alex Cornell: https://www.lennysnewsletter.com/p/how-i-ai-how-meta-designed-muse-with

• Christine Awad on X: https://x.com/christinesed

• Linear’s secret to building beloved B2B products | Nan Yu: https://www.lennysnewsletter.com/p/linears-secret-to-building-beloved-b2b-products-nan-yu

—

Production and marketing by https://penname.co/. For inquiries about sponsoring the podcast, email podcast@lennyrachitsky.com.

—

Lenny may be an investor in the companies discussed.



To hear more, visit www.lennysnewsletter.com



Download audio: https://pscrb.fm/rss/p/api.substack.com/feed/podcast/224231309/2cdd86d5061669c9821d9a2157b09063.mp3
Read the whole story
alvinashcraft
56 minutes ago
reply
Pennsylvania, USA
Share this story
Delete
Next Page of Stories